home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1 / sys / amiga / splitter / splitter.c < prev   
Encoding:
C/C++ Source or Header  |  1993-01-10  |  13.3 KB  |  681 lines

  1. /*    SCCS Id: @(#)splitter.c        3.1   93/01/08
  2. /*    Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1992, 1993 */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #define SOUT    /* split output files */
  6. #define SPLITSIZE (800 * 1024)        /* somewhat < one floppy */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <fcntl.h>
  12.  
  13. #include <proto/exec.h>
  14. #include <exec/types.h>
  15. #include <exec/nodes.h>
  16. #include <exec/lists.h>
  17.  
  18. #include "split.h"
  19. #include "amiout.h"
  20. #include "arg.h"
  21.  
  22. int main(int,char **);
  23.  
  24. char *code_proto="%n.c%C";
  25. char *data_proto="%n.d%D";
  26. char *dir_proto="%n.dir";
  27.  
  28. char trace[MAXTRACEVAR];        /* debugging info */
  29. char *basename;
  30. int datacount;    /* for ssubst - should be replaced */
  31. int codecount;
  32. int data_file_count=0;    /* actual maxima */
  33. int code_file_count=0;
  34. struct hheader hheader;
  35. struct shunk (*hlist)[];
  36. char buf[80];
  37. int wsf_count;
  38.  
  39. main(argc,argv)
  40.     int argc;
  41.     char **argv;
  42. {
  43.     int cur_arg;
  44.  
  45.     arg_init("C:D:d:t:T",argc,argv);
  46.     while((cur_arg=arg_next())!=ARG_DONE){
  47.         switch(cur_arg){
  48.         case 'C':    /* code prototype */
  49.             code_proto=strdup(argarg);break;
  50.         case 'D':    /* data prototype */
  51.             data_proto=strdup(argarg);break;
  52.         case 'd':    /* directions prototype */
  53.             dir_proto=strdup(argarg);break;
  54.         case 't':    /* trace (debug) */
  55.             {
  56.             int dtype=0,dlevel=0;    /* rude defaults */
  57.             sscanf(argarg,"%d=%d",&dtype,&dlevel);
  58.             if(dtype<0 || dtype>=MAXTRACEVAR){
  59.                 fprintf(stderr,"-t: bad trace num ignored\n");
  60.             }else{
  61.                 trace[dtype]=dlevel?dlevel:1;
  62.             }
  63.             break;
  64.             }
  65.         case 'T':    /* trace everything */
  66.             {
  67.             int dtype;
  68.             for(dtype=0;dtype<MAXTRACEVAR;dtype++)trace[dtype]=255;
  69.             }
  70.             break;
  71.         default:
  72.             fprintf(stderr,"Unrecognized option.\n");
  73.             /* FALLTHROUGH */
  74.         case ARG_ERROR:
  75.             panic("Error processing arguments.");
  76.         case ARG_FREE:
  77.             basename=strdup(argarg);
  78.             read_load_file(basename);break;
  79.         }
  80.     }
  81.     renumber();
  82.     out_start(code_proto);
  83.     write_header();
  84.     write_code_file();
  85.     out_stop();
  86.     out_start(data_proto);
  87.     write_data_file();
  88.     out_stop();
  89.     write_dir_file();
  90.     exit(0);
  91. }
  92.  
  93. char *
  94. ssubst(buf,pat)
  95.     char *buf;
  96.     const char *pat;
  97. {
  98.     char *buf1=buf;
  99.  
  100.     while(*pat){
  101.         if(*pat!='%'){
  102.             *buf++=*pat++;
  103.         } else {
  104.             pat++;
  105.             switch(*pat++){
  106.             case '%': *buf++='%';break;
  107.             case 'n': strcpy(buf,basename);buf=eos(buf);break;
  108.             case 'D': sprintf(buf,"%02d",datacount);buf=eos(buf);
  109.                   break;
  110.             case 'C': sprintf(buf,"%02d",codecount);buf=eos(buf);
  111.                   break;
  112.             default:  panic("pattern substitution error");
  113.             }
  114.         }
  115.     }
  116.     *buf='\0';
  117.     return buf1;
  118. }
  119.  
  120. void
  121. panic(s)
  122.     char *s;
  123. {
  124.     fprintf(stderr,"\npanic: %s\n",s);
  125.     exit(1);
  126. }
  127.  
  128. char *
  129. eos(s)
  130.     char *s;
  131. {
  132.     while(*s)s++;
  133.     return s;
  134. }
  135.  
  136. /* input routines */
  137.  
  138.     /* macro for reading the next long.  If e==EOF_OK, caller MUST check
  139.      * for EOF condition via hreadval or assure it can't occur */
  140. static int hreadval=0;        /* macro internal temporary */
  141. #define EOF_OK    1
  142. #define EOF_BAD    0
  143. #define READLONG(e)    \
  144.     ((4!=(hreadval=read(f->fd,&(READLONGx),4)))        \
  145.     ?((0==hreadval && (e)                    \
  146.         ?0                        \
  147.         :rderror()))                    \
  148.     :READLONGx)
  149. static long READLONGx;
  150. #define READSHORT(e)    \
  151.     ((2!=(hreadval=read(f->fd,&(READSHORTx),2)))        \
  152.     ?((0==hreadval && (e)                    \
  153.         ?0                        \
  154.         :rderror()))                    \
  155.     :READSHORTx)
  156. static short READSHORTx;
  157.  
  158. #define LONGLEN(x)    (strlen(x)+3 >>2)    /* # longs for a string */
  159.  
  160. void
  161. read_load_file(name)
  162.     char *name;
  163. {
  164.     int t;
  165.     int hc;
  166.     file *f=NewFile(name);
  167.  
  168.         /* read HUNK_HEADER */
  169.     t=READLONG(EOF_BAD);if(t!=HUNK_HEADER)panic("no HUNK_HEADER");
  170.     t=READLONG(EOF_BAD);if(t)while(t--)READLONG(EOF_BAD); /* eat any name */
  171.     hheader.hcount=READLONG(EOF_BAD);
  172.     hheader.first=READLONG(EOF_BAD);
  173.     hheader.last=READLONG(EOF_BAD);
  174.     if(hheader.hcount !=(hheader.last-hheader.first+1))panic("can't count");
  175.     hheader.sizes=calloc(hheader.hcount,sizeof(int*));
  176.     for(t=0;t<hheader.hcount;t++)
  177.         (*hheader.sizes)[t]=READLONG(EOF_BAD);
  178.  
  179.     hlist=calloc(hheader.hcount,sizeof(struct shunk));
  180.     for(hc=0;hc<hheader.hcount;hc++){
  181.         struct shunk *th = &(*hlist)[hc];
  182.                 /* read each hunk */
  183.         th->h=ReadHunk(f);
  184.     }
  185.     close(f->fd);
  186. }
  187.  
  188. /* write routines */
  189. #define S_CODE    0
  190. #define S_DATA    1
  191.  
  192. void
  193. write_header(){
  194.     int x;
  195.     int target=0;
  196.  
  197.     owrite_long(HUNK_HEADER);
  198.     owrite_long(0);
  199.     owrite_long(hheader.hcount);
  200.     owrite_long(hheader.first);
  201.     owrite_long(hheader.last);
  202.  
  203.     for(x=0;x<hheader.hcount;x++){
  204.         hunk *hp = (*hlist)[x].h;
  205.         if(hp->hunknum==target){
  206.             owrite_long((*hheader.sizes)[x]);
  207.             target++;
  208.         }
  209.     }
  210.     for(x=0;x<hheader.hcount;x++){
  211.         hunk *hp = (*hlist)[x].h;
  212.         if(hp->hunknum==target){
  213.             owrite_long((*hheader.sizes)[x]);
  214.             target++;
  215.         }
  216.     }
  217.     if(target!=hheader.hcount)panic("lost hunks?");
  218. }
  219.  
  220. void
  221. write_code_file(){
  222.     code_file_count=write_split_file(S_CODE)-1;
  223. }
  224.  
  225. void
  226. write_data_file(){
  227.     data_file_count=write_split_file(S_DATA)-1;
  228. }
  229.  
  230. void
  231. write_dir_file(){
  232.     int x;
  233.     FILE *fp=fopen(ssubst(buf,dir_proto),"w");
  234.  
  235.     /*fprintf(fp,"%d %d\n",code_file_count,data_file_count);*/
  236.     for(x=0;x<=code_file_count;x++){
  237.         codecount=x;
  238.         fprintf(fp,"C%s\n",ssubst(buf,code_proto));
  239.     }
  240.     for(x=0;x<=data_file_count;x++){
  241.         datacount=x;
  242.         fprintf(fp,"D%s\n",ssubst(buf,data_proto));
  243.     }
  244.     fclose(fp);
  245. }
  246.  
  247. /* BUGFIX: 9/23/92: see HT() above */
  248. #define HT(x)    ((x) & ~MEM_OBJ_EXTEND)
  249.  
  250. int
  251. write_split_file(fl)
  252.     int fl;
  253. {
  254.     int hc;
  255.     for(hc=0;hc<hheader.hcount;hc++){
  256.         hunk *hp = (*hlist)[hc].h;
  257.         if(fl==S_CODE && HT(hp->rb->id)==HUNK_CODE){
  258.             wsf_hunk(hp);
  259.         } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_DATA){
  260.             wsf_hunk(hp);
  261.         } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_BSS){
  262.             wsf_hunk(hp);
  263.         }
  264.     }
  265.     return wsf_count;
  266. }
  267.  
  268. /* BUGFIX: 9/23/92: see HT() below */
  269. void
  270. wsf_hunk(hp)
  271.     hunk *hp;
  272. {
  273.     listlist *el;
  274.  
  275.     switch(HT(hp->rb->id)){
  276.     case HUNK_CODE:
  277.     case HUNK_DATA:
  278.         owrite(hp->rb->b,(2+hp->rb->b[1])*sizeof(long));
  279.         break;
  280.     case HUNK_BSS:
  281.         owrite(hp->rb->b,2*sizeof(long));
  282.         break;
  283.     default:panic("wsf_hunk: bad type");
  284.     }
  285.     foreach(el,&(hp->reloc),(listlist*)){
  286.         write_lreloc(hp,el);
  287.     }
  288.     owrite_long(HUNK_END);
  289. }
  290.  
  291. void
  292. write_lreloc(hp,ll)
  293.     hunk *hp;listlist *ll;
  294.     {
  295.     block *bp;
  296.     owrite_long(HUNK_RELOC32);
  297.     foreach(bp,&(ll->list),(block*)){
  298.         owrite_long(bp->b[0]);
  299.         owrite_long(((*hlist)[bp->b[1]]).h->hunknum);
  300.         owrite(&(bp->b[2]),bp->b[0]*sizeof(long));
  301.     }
  302.     owrite_long(0);
  303. }
  304.  
  305. void
  306. renumber()
  307. {
  308.     int n;
  309.     n=renumber2(S_CODE,0);
  310.     renumber2(S_DATA,n);
  311. }
  312.  
  313. /* BUGFIX 9/23/92: hp->rb->id must be wrapped with a bit stripper to ignore
  314.  * memory type bits still in that longword.
  315.  */
  316.  
  317. renumber2(fl,n)
  318.     int fl;
  319.     int n;
  320. {
  321.     int hc;
  322.     for(hc=0;hc<hheader.hcount;hc++){
  323.         hunk *hp = (*hlist)[hc].h;
  324.         if(fl==S_CODE && HT(hp->rb->id)==HUNK_CODE){
  325.             hp->hunknum=n++;
  326.         } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_DATA){
  327.             hp->hunknum=n++;
  328.         } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_BSS){
  329.             hp->hunknum=n++;
  330.         }
  331.     }
  332.     return n;
  333. }
  334.  
  335. /* output package */
  336. #ifndef SOUT
  337. /* NB - this version does NOT cope with multiple output files per type */
  338. int ofile;
  339.  
  340. void
  341. out_start(prot)
  342.     char *prot;
  343. {
  344.     datacount=codecount=0;
  345.     ofile=open(ssubst(buf,prot),O_WRONLY|O_CREAT|O_TRUNC);
  346.     if(ofile<0)panic("can't open output file");
  347. }
  348.  
  349. void
  350. out_stop(){
  351.     close(ofile);
  352. }
  353.  
  354. void
  355. owrite_long(literal)
  356.     long literal;
  357. {
  358.     long x=literal;
  359.     owrite(&x,sizeof(x));
  360. }
  361.  
  362. void
  363. owrite(where,len)
  364.     void *where;
  365.     long len;
  366. {
  367.     write(ofile,where,len);
  368. }
  369. #else /* SOUT */
  370. int ofile=0;
  371. int osize;
  372. char *oprot;
  373. void
  374. out_start(prot)
  375.     char *prot;
  376. {
  377.     datacount=codecount=wsf_count=0;
  378.     oprot=prot;
  379.     new_file();
  380. }
  381.  
  382. void
  383. out_stop(){
  384.     close(ofile);
  385.     ofile=0;
  386. }
  387.  
  388. void
  389. owrite_long(literal)
  390.     long literal;
  391. {
  392.     long x=literal;
  393.     if((osize+sizeof(x))>SPLITSIZE)new_file();
  394.     owrite(&x,sizeof(x));
  395.     osize += sizeof(x);
  396. }
  397.  
  398. void
  399. owrite(where,len)
  400.     void *where;
  401.     long len;
  402. {
  403.     if((osize+len)>SPLITSIZE)new_file();
  404.     write(ofile,where,len);
  405.     osize += len;
  406. }
  407.  
  408. void
  409. new_file(){
  410.     if(ofile)close(ofile);
  411.     ofile=open(ssubst(buf,oprot),O_WRONLY|O_CREAT|O_TRUNC);
  412.     if(ofile<0)panic("can't open output file");
  413.     wsf_count++,datacount++,codecount++;
  414.     osize=0;
  415. }
  416. #endif /* SOUT */
  417.  
  418. struct Node *Head(l)
  419.     struct List *l;
  420.     {
  421.     if(!l)panic("Head(NULL)\n");
  422.     return l->lh_Head->ln_Succ?l->lh_Head:0;
  423. }
  424. struct Node *Tail(l)
  425.     struct List *l;
  426. {
  427.     if(!l)panic("Tail(NULL)\n");
  428.     return (l->lh_TailPred==(NODE_P)l)?0:l->lh_TailPred;
  429. }
  430. struct Node *Next(n)
  431.     struct Node *n;
  432. {
  433.     if(!n)printf("Warning: Next(NULL)\n");
  434.     return n?(n->ln_Succ->ln_Succ?n->ln_Succ:0):0;
  435. }
  436. struct Node *Prev(n)
  437.     struct Node *n;
  438. {
  439.     if(!n)printf("Warning: Prev(NULL)\n");
  440.     return n?(n->ln_Pred->ln_Pred?n->ln_Pred:0):0;
  441. }
  442. struct List *_fortemp;    /* scratch for foreach macro */
  443.  
  444. void
  445. dump_after_read(struct List *root){
  446.     file *f;
  447.     foreach(f,root,(file *)){
  448.         punit *p;
  449.         printf("FILE '%s'\n",f->name);
  450.         foreach(p,&(f->punits),(punit *)){
  451.         hunk *h;
  452.         print_text_block("\tPUNIT %.*s\n",p->unit_header);
  453.         if(p->libsize){
  454.         printf("\tlibsize=%08x\n",p->libsize);
  455.         } else {
  456.         /* */
  457.         }
  458.         foreach(h,&(p->hunks),(hunk *)){
  459.         print_text_block("\t\tHUNK %.*s",h->name);
  460.         printf(" @%08x\n",h);
  461.         print_bin_block(h->rb);
  462.         printf("\t\t\tCode Reloc\n");
  463.         printf("\t\t\tData Reloc\n");
  464.         if(h->merge)printf("\t\t\tmerge(%08x)\n",h->merge);
  465.         if(h->hunkstart)printf("\t\t\thunkstart\n");
  466.         if(h->hunkchain)printf("\t\t\thunkchain\n");
  467.         if(h->hunkgone)printf("\t\t\thunkgone\n");
  468.         printf("\t\t\toverlay(%08x) hunknum(%08x) offset(%08x)\n",
  469.           h->overlay,h->hunknum,h->hunkoffset);
  470.         }
  471.         }
  472.     }
  473. }
  474.  
  475. void
  476. print_text_block(char *fmt,block *b){
  477.     if(!b){
  478.         printf(fmt,10,"(no block)");
  479.     } else {
  480.         if(b->sw){
  481.             printf(fmt,13,"(swapped out)");
  482.         } else {
  483.             if(!(b->b[1]) || !*(char*)&(b->b[2])){
  484.                 printf(fmt,6,"(null)");
  485.             } else {
  486.                 printf(fmt,b->b[1]*4,&(b->b[2]));
  487.             }
  488.         }
  489.     }
  490. }
  491.  
  492. void
  493. print_bin_block(block *b){
  494.     if(b->sw){
  495.         printf("\t\t\t(swapped out)\n");
  496.     } else {
  497.         printf("\t\t\tid1=%08x id2=%08x len=%08x\n",
  498.           b->id,b->b[0],b->b[1]);
  499.     }
  500. }
  501.  
  502. /*
  503.  * read routines
  504.  */
  505.  
  506. /*
  507.  * ReadSimpleBlock
  508.  * If the given id is recognized as a simple block (id, length, data),
  509.  * allocate and fill in a block structure.  Include the id in the block.
  510.  */
  511. block *ReadSimpleBlock(f,id)
  512.     file *f;
  513.     long id;
  514.     {
  515.     long len;
  516.     long hid;
  517.     block *b;
  518.  
  519.     hid=id & 0x0fffffff;
  520.     if(    hid !=HUNK_UNIT && hid != HUNK_NAME && hid != HUNK_CODE &&
  521.         hid != HUNK_DATA && hid != HUNK_BSS && hid != HUNK_DEBUG
  522.       ){
  523.         printf("%08x\n",id);
  524.         panic("ReadSImpleBlock");
  525.     }
  526.  
  527.     len=READLONG(EOF_BAD);
  528.     b=NewBlock();
  529.     b->id=id;
  530.     b->sw=0;
  531.     b->b=NewData((hid==HUNK_BSS)?2:len+2);
  532.     b->b[0]=id;
  533.     b->b[1]=len;
  534.     if(hid != HUNK_BSS)read(f->fd,&(b->b[2]),len*4);
  535.     return(b);
  536. }
  537.  
  538. /*
  539.  * TossSimpleBlock
  540.  * Skip past something we don't need.
  541.  */
  542. int TossSimpleBlock(f)
  543.     file *f;
  544.     {
  545.     long len=READLONG(EOF_BAD);
  546.     if(len)if( lseek(f->fd,len*4,1) == -1)panic("Toss failed\n");
  547.     return(len);
  548. }
  549.  
  550. /*
  551.  * ReadHunk
  552.  * Read an entire hunk, building lists of each block type in the given hunk
  553.  * structure.  If we are listing, do the listing as we read so we can see
  554.  * where things die if we hit a type code we don't recognize.
  555.  */
  556. hunk *ReadHunk(f)
  557.     file *f;
  558.     {
  559.     long id;
  560.     hunk *h=NewHunk();
  561.     while(1){
  562.         id=READLONG(EOF_OK);
  563.         switch(id & 0x0fffffff){    /* ignore memory type bits */
  564.         case 0: return 0;        /* EOF - not good test */
  565.         case HUNK_RELOC32:
  566.             LIST{printf("Reloc32:\n");}
  567.             ReadReloc(f,id,&h->reloc);break;
  568.         case HUNK_CODE:
  569.             h->rb=ReadSimpleBlock(f,id);
  570.             LIST{printf("Code size %d\n",block_size(h->rb)*4);};
  571.             break;
  572.         case HUNK_DATA:
  573.             h->rb=ReadSimpleBlock(f,id);
  574.             LIST{printf("Data size %d\n",block_size(h->rb)*4);};
  575.             break;
  576.         case HUNK_BSS:
  577.             h->rb=ReadSimpleBlock(f,id);
  578.             LIST{printf("Bss size %d\n",block_size(h->rb)*4);};
  579.             break;
  580.         case HUNK_SYMBOL:
  581.             while(TossSimpleBlock(f))READLONG(EOF_BAD);
  582.             LIST{printf("Symbols skipped\n");};
  583.             break;
  584.         case HUNK_DEBUG:
  585.             (void)TossSimpleBlock(f);
  586.             LIST{printf("Debug hunk skipped\n");};
  587.             break;
  588.         case HUNK_END:    LIST{printf("End of hunk\n");};return h;
  589.         case HUNK_BREAK:LIST{printf("End of overlay\n");};break;
  590.         default:
  591.             printf("Lost id=0x%x\n",id);exit(2);
  592.         }
  593.     }
  594.     return 0;
  595. }
  596.  
  597. /*
  598.  * ReadReloc
  599.  * Read a relocation block and build a linked list of the sections.
  600.  * If we are listing, do that now.
  601.  */
  602. void ReadReloc(f,id,ls)
  603.     file *f;
  604.     long id;
  605.     struct List *ls;
  606.     {
  607.     long len;
  608.     block *cur;
  609.     listlist *blist=NewListList();
  610.     AddTail(ls,blist);
  611.     blist->id=id;
  612.     len=READLONG(EOF_BAD);
  613.     while(len){
  614.         cur=NewBlock();
  615.         cur->b=NewData(len+2);
  616.         read(f->fd,&(cur->b[1]),len*4+4);
  617.         cur->b[0]=len;
  618.         LIST{printf("\thunk #%d - %d items\n",cur->b[1],len);}
  619.         AddTail(&blist->list,cur);
  620.         /*ReadLong(len);*/
  621.         len=READLONG(EOF_BAD);
  622.     }
  623. }
  624.  
  625. int rderror(){
  626.     panic("read error\n");
  627.     return 0;    /* just to make it quiet - NOTREACHED */
  628. }
  629.  
  630. long block_size(blk)
  631.     block *blk;
  632. {
  633.     return(blk->b[1]);
  634. }
  635.  
  636. /* Allocation routines - if this was C++ then this code would be buried in the
  637.  * constructors.  Doing it this way means we can re-write the allocation later
  638.  * to allocate things we'll need lots of in larger blocks to avoid the time and
  639.  * space penalties of malloc. */
  640. file *NewFile(fname)
  641.     char *fname;
  642.     {
  643.     file *ret=calloc(sizeof(file),1);
  644.     NewList(&ret->punits);
  645.     ret->name=strdup(fname);
  646.     ret->fd= open(fname,O_RDONLY);
  647.     return(ret);
  648. }
  649.  
  650. punit *NewPunit(){
  651.     punit *ret=calloc(sizeof(punit),1);
  652.     NewList(&ret->hunks);
  653.     return(ret);
  654. }
  655.  
  656. hunk *NewHunk(){
  657.     hunk *ret=calloc(sizeof(hunk),1);
  658.     NewList(&ret->reloc);
  659.     NewList(&ret->dreloc);
  660.     NewList(&ret->extsym);
  661.     ret->overlay=UNASSIGNED_HUNK;
  662.     return(ret);
  663. }
  664.  
  665. block *NewBlock()
  666.     {
  667.     return calloc(sizeof(block),1);
  668. }
  669.  
  670. listlist *NewListList(){
  671.     listlist *ret=calloc(sizeof(listlist),1);
  672.     NewList(&ret->list);
  673.     return(ret);
  674. }
  675.  
  676. long *NewData(longs)
  677.     long longs;    
  678.     {
  679.     return(malloc(longs*4));
  680. }
  681.